﻿using ECommon.Configurations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Reflection;

namespace QuickStart
{
    using ECommon.Autofac;
    using ECommon.Components;
    using ECommon.Configurations;
    using ECommon.JsonNet;
    using ECommon.Log4Net;
    using ECommon.Logging;
    using ECommon.Utilities;
    using ENode.Configurations;
    using EQueue.Broker;
    using EQueue.Configurations;
    using Infrastructure;
    using ENode.Infrastructure;
    using ECommon.Socketing;

    public partial class Bootstrap
    {
        public static void Init()
        {
            ConfigSettings.Initialize();
            InitializeECommon();
            try
            {
                InitializeEQueue();
            }
            catch (Exception ex)
            {
                _logger.Error("Initialize EQueue failed.", ex);
                throw;
            }

            try
            {
                InitializeENode();
            }
            catch (Exception ex)
            {
                _logger.Error("Initialize ENode failed.", ex);
                throw;
            }

        }

        private static ILogger _logger;
        private static Configuration _ecommonConfiguration;
        private static ENodeConfiguration _enodeConfiguration;
        private static BrokerController _broker;


        private static void InitializeECommon()
        {
            _ecommonConfiguration = Configuration
                .Create()
                .UseAutofac()
                .RegisterCommonComponents()
                .UseLog4Net()
                .UseJsonNet()
                .RegisterUnhandledExceptionHandler();


            _logger = ObjectContainer.Resolve<ILoggerFactory>().Create(typeof(Bootstrap).FullName);
            _logger.Info("ECommon initialized.");
        }


        private static void InitializeEQueue()
        {
            //  消息存储于数据库中…
            //  select cast([Body] as varchar(max)) from [_EQueue].[dbo].[Message]

            var queueStoreSetting = new SqlServerQueueStoreSetting
            {
                ConnectionString = ConfigSettings.EQueueConnectionString
            };
            var messageStoreSetting = new SqlServerMessageStoreSetting
            {
                ConnectionString = ConfigSettings.EQueueConnectionString
            };
            var offsetManagerSetting = new SqlServerOffsetManagerSetting
            {
                ConnectionString = ConfigSettings.EQueueConnectionString
            };


            _ecommonConfiguration.RegisterEQueueComponents()//;
            .UseSqlServerQueueStore(queueStoreSetting)
            .UseSqlServerMessageStore(messageStoreSetting)
            .UseSqlServerOffsetManager(offsetManagerSetting);

            ConfigSettings.Initialize();
            var setting = new BrokerSetting
            {
                ProducerAddress = new IPEndPoint(SocketUtils.GetLocalIPV4(), ConfigSettings.BrokerProducerPort),
                ConsumerAddress = new IPEndPoint(SocketUtils.GetLocalIPV4(), ConfigSettings.BrokerConsumerPort),
                AdminAddress = new IPEndPoint(SocketUtils.GetLocalIPV4(), ConfigSettings.BrokerAdminPort)
            };

            _broker = BrokerController.Create(setting);
            _logger.Info("EQueue initialized.");

            try
            {
                _broker.Start();
                _logger.Info("EQueue Started.");
            }
            catch (Exception ex)
            {
                _logger.Error("Broker start failed.", ex);
                throw;
            }
        }




        private static void InitializeENode()
        {
            var assemblies = new[]
            {
                Assembly.Load("Infrastructure"),

                Assembly.Load("Commands"),
                Assembly.Load("CommandHandlers"),

                Assembly.Load("Domain"),
                Assembly.Load("Domain.Ef"),

                Assembly.Load("Denormalizers.Ef"),

                Assembly.Load("Messages"),
                Assembly.Load("MessagePublishers"),

                Assembly.Load("ProcessManagers"),
                Assembly.GetExecutingAssembly()
            };


            var setting = new ConfigurationSetting
            {
                SqlDefaultConnectionString = ConfigSettings.ENodeConnectionString
            };

            _enodeConfiguration = _ecommonConfiguration
                .CreateENode(setting)
                .RegisterENodeComponents()
                .RegisterBusinessComponents(assemblies)
                .RegisterAllTypeCodes()
                .UseSqlServerLockService()

                .UseSqlServerCommandStore()
                .UseSqlServerEventStore()
                .UseSqlServerSequenceMessagePublishedVersionStore()
                .UseSqlServerMessageHandleRecordStore()

                .UseEQueue()
                .InitializeBusinessAssemblies(assemblies);
            _logger.Info("ENode initialized.");


            _enodeConfiguration.StartEQueue();


        }

    }
}
